C
and C++ Design Considerations
Component
objects contain data specific to the object and one or more interface
implementations. The data is private and inaccessible from outside the object,
while the interface implementations are public and you can access them through
pointers.
Because
interfaces are a binary standard, interface implementation is language
independent. However, C++ is the preferred language because it supports many of
the object-oriented concepts inherent in OLE. Using a procedural language such
as C involves extra work, as summarized below:
You must explicitly initialize
VTBLs either at compile-time or run-time and you should not change them later.
Once initialized with function pointers, those pointers should remain unchanged
until the application shuts down. VTBLs in C++ are declared as constants to
prevent them from being modified inadvertently. However, in C there is no way
to ensure that a VTBL will remain unchanged.
To overcome this difference, OLE provides a mechanism that lets C
developers declare VTBLs as constants. To do so, place the following statement
before the #include statement for the ole2.h header file:
#define CONST_VTABLE
Each method requires a pointer
to the object that owns the method. In C++, all members are implicitly
dereferenced off the this pointer. In C, there must be an additional
first parameter passed to each method that is a pointer to the interface in
which the method is declared.
Methods in C++ can have
identical names because methods are actually known by a name that is the result
of concatenating the method name to the class name. Methods in C must have a
unique name to designate the object with which they are associated.
For example,
the following C++ code sample defines an implementation of IUnknown::QueryInterface
CUnknown::QueryInterface (REFIID riid, LPVOID *
ppvObj);
A similar C
implementation would require a more complex name and an additional first
parameter to indicate the object owning the method:
IUnknown_Doc_QueryInterface (LPUNKNOWN pUnk, REFIID
riid,
LPVOID *
ppvObj);
The following
sections demonstrate how to declare a component object in a few typical ways:
using C nested data structures, C++ nested classes, and C++ multiple
inheritance. The demonstration object, called CObj, derives from IUnknown